/**
 * Candidate number: 35834
 */
package tv.starfu.systems;

import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.EntitySystem;
import com.artemis.GroupManager;
import com.artemis.IntervalEntitySystem;
import com.artemis.utils.ImmutableBag;
import net.beadsproject.beads.core.AudioContext;
import net.beadsproject.beads.data.Sample;
import net.beadsproject.beads.data.SampleManager;
import net.beadsproject.beads.ugens.Envelope;
import net.beadsproject.beads.ugens.Gain;
import net.beadsproject.beads.ugens.SamplePlayer;
import tv.starfu.game.EntityType;
import tv.starfu.sequencer.components.AmpEnvelope;
import tv.starfu.sequencer.components.PitchEnvelope;
import tv.starfu.sequencer.components.SamplePlayback;
import tv.starfu.sequencer.components.TimeVector;
import tv.starfu.utils.Music;

/**
 * process entities with given component types
 * @author nia radical
 */
public class DrumSequencerSystem extends EntitySystem {

    private TimeVector now;
    private AudioContext ac;
    private SampleManager sm;
    private Gain gain;
    
    private ComponentMapper<TimeVector> tvMapper;
    private ComponentMapper<AmpEnvelope> ampEnvMapper;
    private ComponentMapper<PitchEnvelope> pitchEnvMapper;
    private ComponentMapper<SamplePlayback> sampleMapper;

    public DrumSequencerSystem(AudioContext ac, TimeVector now) {
        super(TimeVector.class, SamplePlayback.class, AmpEnvelope.class, PitchEnvelope.class);
        this.now = now;
        this.ac = ac;
    }
    
    @Override
    public void initialize() {
         tvMapper       = new ComponentMapper<TimeVector>(TimeVector.class, world);
         ampEnvMapper   = new ComponentMapper<AmpEnvelope>(AmpEnvelope.class, world);
         pitchEnvMapper = new ComponentMapper<PitchEnvelope>(PitchEnvelope.class, world);
         sampleMapper   = new ComponentMapper<SamplePlayback>(SamplePlayback.class, world);
         
         /* Loads Samples into SampleManager */
         sm = new SampleManager();
         SampleManager.group("kick", new Sample[] 
	 			{ 
                                  /* KICKS */
                                  SampleManager.sample("Assets/Sounds/drumsounds/b1.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b2.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b3.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b4.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b5.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b6.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b7.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/b8.wav")
                                });
         
         SampleManager.group("snare", new Sample[]                         
                                {
                                  /* SNARES */
                                  SampleManager.sample("Assets/Sounds/drumsounds/s1.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/s2.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/s3.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/s4.wav")
                                });
         
         SampleManager.group("oh", new Sample[]                         
                                {                  
                                  /* OPEN HATS */
                                  SampleManager.sample("Assets/Sounds/drumsounds/oh1.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/oh2.wav")
                                });
         
         SampleManager.group("ch", new Sample[]                         
                                {                 
                                  /* CLOSED HATS */
				  SampleManager.sample("Assets/Sounds/drumsounds/ch1.wav"),
				  SampleManager.sample("Assets/Sounds/drumsounds/ch2.wav")
                                  
                                });
         gain         = new Gain(ac, 1, 0.3f);
         ac.out.addInput(gain);
    }

    @Override
    protected void processEntities(ImmutableBag<Entity> entities) {
        /* Get relevant Entity Group */
        GroupManager groupMgr = world.getGroupManager();
	ImmutableBag<Entity> soundEvents = groupMgr.getEntities(EntityType.DRUMHIT.toString());
        
        /* Process all events with group: SOUNDEVENT */
        processEvents(soundEvents);
    }

    @Override
    protected boolean checkProcessing() {
        return true;
    }
    
    /**
     * Processes SoundEvent Entities by comparing their TimeVector against the current time 
     * @param events    Group of SOUNDEVENT entities
     */
    private void processEvents(ImmutableBag<Entity> events) {
       
            // Go through list of SoundEvents, retrieve TV
            for(int i = 0; i < events.size(); ++i) {
                Entity a = events.get(i);
                TimeVector tv = tvMapper.get(a);

                playSound(a); }
            
    }

    /**
     * Play the sounds of an entity...
     * @param e     Entity
     */
    private void playSound(Entity e) {
        // Get TV components from each Event entity       
                
        TimeVector      tv           = tvMapper.get(e);
        AmpEnvelope     ampEnv       = ampEnvMapper.get(e);
        PitchEnvelope   pitchEnv     = pitchEnvMapper.get(e);
        SamplePlayback  sample       = sampleMapper.get(e);

        String          sampleGroup  = sample.getSampleGroup();
        Envelope        amp          = ampEnv.getEnvelope();
        
        
        // compare TV to currentTV
        if (tv.compareTo(now) == 0) {
            System.out.println("Play Me: "+tv.toString());
            SamplePlayer sp = new SamplePlayer(ac, SampleManager.fromGroup(sampleGroup, sample.getSampleIndex()));
            sp.setKillOnEnd(true);
            gain.addInput(sp);
            
            System.out.println("BOOM: " + sample.getSampleGroup());
            e.delete();
        }
        
    }
    
}

